
package com.waitingsnow.common.share.qqMicroBlog.core
{
	import com.hurlant.crypto.Crypto;
	import com.hurlant.crypto.hash.HMAC;
	import com.hurlant.util.Base64;
	import com.hurlant.util.Hex;
	import com.waitingsnow.common.share.qqMicroBlog.lang.MessageCollection;
	import com.waitingsnow.common.share.qqMicroBlog.support.WeiboUtil;
	import com.waitingsnow.core.debug.Logger;
	
	import flash.net.SharedObject;
	import flash.utils.ByteArray;

	/**
	 * 核心类，包含一些重要数据，比如：应用ID，密钥，令牌
	 * 采用单例模式，请使用静态方法getInstance()获取它的唯一实例
	 * 用户除了要设置一些初始值，后面的操作基本都通过包api中的类来进行
	 * @langversion 3.0
	 * @playerversion Flash 9
	 * @playerversion AIR 1.1
	 */	
	public class WeiboConfig
	{
		/**
		 * @private
		 * 持有的唯一实例
		 */		
		private static var instance:WeiboConfig;
		/**
		 * 应用的ID
		 * 获取方式参见腾讯微博开放平台您的应用详细信息部分
		 */		
		public var appKey:String;
		/**
		 * 应用的密钥
		 * 获取方式同appkey
		 */		
		public var appSecret:String;
		/**
		 * 如果是WEB认证方式，则需要指定一个回调的URL;如果是APP形式则不需要配置这个地方
		 */		
		public var oauthCallback:String;
		/**
		 * 基于HTTPS的API调用的URL的前缀地址
		 * @default https://open.t.qq.com/cgi-bin/
		 */		
		public var encryptURLBase:String = "http://open.t.qq.com/cgi-bin/";
		/**
		 * 基于HTTP的API调用的URL的前缀地址
		 * @default http://open.t.qq.com/api/
		 */		
		public var urlBase:String = "http://open.t.qq.com/api/";
		/**
		 * HMAC版本
		 */		
		public const HMACSHA1:String = "HMAC-SHA1";
		/**
		 * HMAC类型
		 */		
		public const HMACSHATYPE:String = "sha1";
		/**
		 * OAuth版本
		 */		
		public const oauthVersion:String = "1.0";
		/**
		 * 临时授权的Token
		 */		
		public var tempOauthToken:String;
		/**
		 * 临时授权的密钥
		 */		
		public var tempOauthSecret:String;
		/**
		 * 正式授权的Token
		 */		
		public var oauthToken:String;
		/**
		 * 正式授权的密钥
		 */		
		public var oauthSecret:String;
		/**
		 * 应用使用GET或者POST来传值，用来设置允许两种方式的API，某些只允许POST方式的API将忽略这个设置
		 * @default GET
		 */	
		public var requestMethod:String = "GET";
		/**
		 * 返回数据的封装格式，可以是string,json或xml
		 * @default json
		 */	
		public var dataFormat:String = "json";
		
		/**
		 * @private
		 * 缓存参数
		 */		
		private var so:SharedObject;
		/**
		 * oauth请求的签名，根据oauth协议中算法生成basestring 后，用appsecret 对basestring 经hmac_sha1生成的签名串
		 * @param httpMethod GET或POST
		 * @param url 请求的API的地址
		 * @param parms 传递的参数
		 * @param currentTokenSecret Token的密钥，第一次requestToken无需密钥，当accessToken传递临时密钥，其它情况传递正式密钥
		 * @return 签名字符串
		 * 
		 */			
		public function getOauthSignature(httpMethod:String,url:String,parms:Object,currentTokenSecret:String=""):String
		{
			if(appKey == null || appSecret == null)
				Logger.error("getOauthSignature:{0}",MessageCollection.noAppKeyError);
			//create Signature Base String
			var baseUri:String = encodeURIComponent(url);
			var parmsArr:Array = [];
			for(var parmName:String in parms)
			{
				parmsArr.push({name:encodeURIComponent(parmName),value:encodeURIComponent(parms[parmName])});
			}
			parmsArr.sortOn("name");
			var sortedParams:Array = [];
			for each(var item:Object in parmsArr)
			{
				sortedParams.push(item.name+"%3D"+item.value);
			}
			var sortedParamsString:String = sortedParams.join("%26");
			var signatureBaseString:String = httpMethod+"&"+baseUri+"&"+sortedParamsString;
			//HMAC
			var hmac:HMAC = Crypto.getHMAC(HMACSHATYPE);
			var secretString:String = encodeURIComponent(appSecret)+"&"+encodeURIComponent(currentTokenSecret);
			var keyBytes:ByteArray = Hex.toArray(Hex.fromString(secretString));
			var messageBytes:ByteArray = Hex.toArray(Hex.fromString(signatureBaseString));
			var resultBytes:ByteArray = hmac.compute(keyBytes,messageBytes);
			var encodedString:String = Base64.encodeByteArray(resultBytes);
			return encodeURIComponent(encodedString);
		}
		/**
		 * 获取调用API所需的标准参数
		 * @param currentToken 传入所需的token，如果存在的话
		 * @return 携带参数的对象
		 */		
		public function getStandardParameters(currentToken:String=null):Object
		{
			if(appKey == null || appSecret == null)
				Logger.error("getStandardParameters:{0}",MessageCollection.noAppKeyError);
			var parms:Object = {};
			parms.oauth_consumer_key = appKey;
			parms.oauth_nonce = WeiboUtil.getRandomChars(32);
			parms.oauth_signature_method = HMACSHA1;
			parms.oauth_timestamp = WeiboUtil.getTimestamp();
			parms.oauth_version = oauthVersion;
			if(currentToken != null)
				parms.oauth_token = currentToken;
			return parms;
		}
		/**
		 * 外部应该调用这个方法获取TencentWeibo的唯一实例
		 * @return TencentWeibo的唯一实例
		 * 
		 */		
		public static function getInstance():WeiboConfig
		{
			if(instance == null)
			{
				instance = new WeiboConfig(new InnerClass());
			}
			return instance;
		}
		
		/**
		 * 构造方法
		 * @param virtualObject 这个参数没有实际意义，只是为了保证外部无法调用构造方法，因为类型是内部类，外部不具备实例化它的条件
		 * 
		 */		
		public function WeiboConfig(virtualObject:InnerClass)
		{
			//do nothing
		}
		/**
		 * 初始化
		 * @param appKey 应用ID
		 * @param appSecret 应用密钥
		 * @param oauthCallback 应用的回调地址
		 * @example
		 * <pre>
		 * var config:WeiboConfig = WeiboConfig.getInstance();
		 * config.initialize(appKey,appSecret,oauthCallback);
		 * </pre>
		 */		
		public function initialize(appKey:String,appSecret:String,oauthCallback:String=null):void
		{
			if(appKey == null || appSecret == null || appKey == "" || appSecret == "")
			{
				Logger.error("initialize:{0}",MessageCollection.appKeyInvalid);
				return;
			}
			this.appKey = appKey;
			this.appSecret = appSecret;
			if(oauthCallback != null)
				this.oauthCallback = oauthCallback;
			so = SharedObject.getLocal("shareKit/TencentWeibo");
			if(so.data.tempOauthToken != null)
				tempOauthToken = so.data.tempOauthToken;
			if(so.data.tempOauthSecret != null)
				tempOauthSecret = so.data.tempOauthSecret;
			if(so.data.oauthToken != null)
				oauthToken = so.data.oauthToken;
			if(so.data.oauthSecret != null)
				oauthSecret = so.data.oauthSecret;
		}
		/**
		 * 将参数缓存参数到本地
		 * @param key 名称
		 * @param value 值
		 * 
		 */		
		public function cacheToLocal(key:String,value:String):void
		{
			so.data[key] = value;
			so.flush();
		}
		/**
		 * 删除缓存
		 */		
		public function clearCache():void
		{
			cacheToLocal("tempOauthToken",null);
			cacheToLocal("tempOauthSecret",null);
			cacheToLocal("oauthToken",null);
			cacheToLocal("oauthSecret",null);
			so = null;
		}
	}
}
/**
 * 这是一个内部类，没有实际作用，只是为了保证在外部TencentWeibo不会被new的方式实例化
 */
class InnerClass {}